home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / snip0493.zip / GLBL_ENV.C < prev    next >
C/C++ Source or Header  |  1993-04-05  |  10KB  |  365 lines

  1. /*****************************************************************************
  2.    This code is based upon the program SETPATH.PAS (located in BPROGA) by
  3.    David Dubois [71401,747]
  4.  
  5.    This Turbo C version is written by Peter Thomas [75716,2377]
  6.  
  7.    This series of routines are designed to Locate, Retrieve, Update, and
  8.    Remove "Variables" from the MASTER copy of the DOS Environment table.
  9.    The routines have been written in a manner that avoids linking any
  10.    EXTERNAL routines for string manipulation, and thus should be independent
  11.    of memory model being used.
  12.  
  13.    Be careful that changes made to the Environment with these routines
  14.    ONLY OCCUR IN THE MASTER COPY, and that if COMMAND.COM is spawned
  15.    from a routine that has changed the environment, NO CHANGES WILL BE
  16.    SEEN IN THE ENVIRONMENT. This is most apparent when this program is run
  17.    in the INTEGRATED environment: changes made by this technique will
  18.    not appear if the "OS Shell" is invoked, and will only appear on exit
  19.    from TC.
  20.  
  21.    For full documentation on the techniques used here can be found in the
  22.    file COMENV.ARC located in LIB 2 of BPROGA on Compuserve.
  23.  
  24.    As David Dubois says:
  25.  
  26.   I hereby dedicate this knowledge to the public domain. Feel free to use
  27.   it, but if you do, please mention my name. There are no guarantees, and
  28.   in fact, I wouldn't bet a dollar that it will work every time.
  29.  
  30.   That this works at all is based on experimental, rather than properly
  31.   documented, evidence. There are no guarantees. But then, its free.
  32.  
  33. *****************************************************************************/
  34.  
  35. #include <stdio.h>
  36. #include <dos.h>
  37.  
  38. #ifdef __ZTC__
  39.  #error ZTC/C++ not supported - huge pointers required!
  40. #endif
  41.  
  42. #ifdef __TURBOC__
  43.  #include <alloc.h>
  44.  #define Fmalloc farmalloc
  45.  #define Ffree farfree
  46. #else
  47.  #include <malloc.h>
  48.  #include <stdlib.h>
  49.  #define far  _far
  50.  #define Fmalloc _fmalloc
  51.  #define Ffree _ffree
  52.  #define MK_FP(seg,offset) \
  53.         ((void far *)(((unsigned long)(seg)<<16) | (unsigned)(offset)))
  54. #endif
  55.  
  56. /*
  57.  *   Mstr_FindEnvironment:
  58.  *     Scans for the "Master" Environment area, and returns
  59.  *     a pointer to it, and the size of the environment.
  60. */
  61. void Mstr_FindEnvironment ( char far **Env , unsigned *EnvSize )
  62. {
  63.    unsigned int far *CommandSeg, far *TempSeg ;
  64.    char far *BlockSeg ;
  65.  
  66.    /*
  67.     *  Scan through PSP's looking for a block that is its own father.
  68.     *  This block is the PSP of COMMAND.COM
  69.    */
  70.   TempSeg = MK_FP ( _psp , 0 ) ;
  71.    do
  72.    {
  73.      CommandSeg = TempSeg ;
  74.      TempSeg = MK_FP ( *(TempSeg+8) , 0 ) ;
  75.    }
  76.    while ( TempSeg != CommandSeg ) ;
  77.  
  78.    /*
  79.     *  Scan forward through memory looking for the correct MSB.
  80.     *  This will have COMMAND.COM's PSP as owner, and begin with
  81.     *  the character M
  82.    */
  83.    BlockSeg = (char far *)CommandSeg ;
  84.    do
  85.    {
  86.     BlockSeg = MK_FP ( FP_SEG(BlockSeg)+1 , 0 ) ;
  87.    }
  88.    while ( ( *(unsigned int far *)(BlockSeg+1) != FP_SEG ( CommandSeg ) ) ||
  89.            ( *BlockSeg != 'M' ) ) ;
  90.  
  91.    /*
  92.     *  The environment is the NEXT segment of memory
  93.     *  and bytes 4 and 5 are the size in paragraphs
  94.    */
  95.    *Env = MK_FP ( FP_SEG(BlockSeg)+1 , 0 ) ;
  96.    *EnvSize = 16 * *(unsigned int far *)(BlockSeg+3) ;
  97. }
  98.  
  99. /*
  100.  *   Mstr_getenv:
  101.  *     Scans the "Master" Environment for a given "sub string"
  102.  *     and returns a pointer to it.
  103.  *     Similar to Turbo routine "getenv" but uses the Master copy of the
  104.  *     environment table.
  105. */
  106. char far *Mstr_getenv (char far *Env , char far *name)
  107. {
  108.    char far *Sub_Env, far *str1, far *str2 ;
  109.  
  110.    /*
  111.     *  Start at the beginning of the environment
  112.    */
  113.    Sub_Env = Env ;
  114.  
  115.    /*
  116.     *  While the "sub string" we're looking at is non-zero
  117.    */
  118.    for ( ; *Sub_Env ; )
  119.    {
  120.      /*
  121.       *  Simulate a "strcmp" on the "sub string" of the environment
  122.       *  and the string we're looking for
  123.      */
  124.      for ( str1 = Sub_Env , str2 = name ;
  125.            (*str1) && (*str2) && ( *str1 == *str2) ;
  126.            str1++ , str2++ ) ;
  127.      /*
  128.       *  If we reached the end of the string we're looing for
  129.       *  we've found the correct portion of the environment.
  130.       *  Return the ptr to the start of this "sub string"
  131.      */
  132.      if ( !*str2 )
  133.        return ( Sub_Env ) ;
  134.  
  135.      /*
  136.       *  Otherwise, advance to the next "sub string" in the environment
  137.       *  by performing a "strchr" function
  138.      */
  139.      for ( ; *(Sub_Env++) ; ) ;
  140.    }
  141.  
  142.    /*
  143.     *  Obviously, the string is not present in the environment.
  144.     *  Return this fact.
  145.    */
  146.   return ( NULL ) ;
  147. }
  148.  
  149. /*
  150.  *   Mstr_delenv:
  151.  *     Scans the "Master" Environment for a given "sub string"
  152.  *     and removes it.
  153. */
  154. int Mstr_delenv (char far *Env , unsigned EnvSize , char far *name)
  155. {
  156.    char far *Sub_Env , far *New_Env ;
  157.    char huge *Dest , far *Src , huge *End_Env ;
  158.  
  159.    int Done  ;
  160.    unsigned Ctr ;
  161.  
  162.    /*
  163.     *  Allocate a chunk of storage to act as a "working" copy of
  164.     *  the Environment table
  165.    */
  166.    New_Env = Fmalloc ( EnvSize ) ;
  167.  
  168.    /*
  169.     *  Copy the data from the Master to Working copy of the
  170.     *  Environment table.
  171.     *  Simulates a "memcpy" function.
  172.    */
  173.    for ( Src = Env , Dest = (char far *)New_Env , Ctr = 0 ;
  174.          Ctr < EnvSize ;
  175.          *(Dest++) = *(Src++) , Ctr++ ) ;
  176.  
  177.    /*
  178.     *  Scan the working copy of the environment for the desired
  179.     *  sub string
  180.    */
  181.    Sub_Env = Mstr_getenv ( New_Env , name ) ;
  182.  
  183.    if ( Sub_Env == NULL )
  184.    {
  185.      /*
  186.       *  If not found, do nothing
  187.      */
  188.      Done = -1 ;
  189.    } else {
  190.      /*
  191.       *  Locate the end of the string to delete
  192.       *  Simulate a "strchr" call
  193.      */
  194.      for ( Src = Sub_Env ; *(Src++) ; ) ;
  195.  
  196.      /*
  197.       *  Move the rest of the environment back over the "sub string"
  198.       *  being deleted.
  199.       *  Simulated "memcpy" function.
  200.       *  Huge pointers used for pointer comparison purposes.
  201.      */
  202.      for ( Dest = (char huge *)Sub_Env , End_Env = (char huge *) (New_Env + EnvSize ) ;
  203.          ( Dest < End_Env ) ;
  204.          *(Dest++) = *(Src++) ) ;
  205.  
  206.      /*
  207.       *  Copy the data from the Working to Master copy of the
  208.       *  Environment table.
  209.       *  Simulates a "memcpy" function.
  210.      */
  211.      for ( Src = New_Env , Dest = (char huge *)Env , Ctr = 0 ;
  212.          Ctr < EnvSize ;
  213.          *(Dest++) = *(Src++) , Ctr++ ) ;
  214.  
  215.      /*
  216.       *  Signal all done
  217.      */
  218.      Done = 0 ;
  219.    }
  220.  
  221.    /*
  222.     *  Free all working storage
  223.    */
  224.    Ffree ( New_Env ) ;
  225.  
  226.    return ( Done ) ;
  227. }
  228.  
  229. /*
  230.  *   Mstr_putenv:
  231.  *     Adds/Replaces a given "sub string" in the Master Environment.
  232.  *     Similar to Turbo routine "putenv" but uses the Master copy of the
  233.  *     environment table.
  234. */
  235. int Mstr_putenv (char far *Env , unsigned EnvSize , char far *name )
  236. {
  237.    char far *Sub_Env , far *Temp_Name ;
  238.    char huge *Dest , far *Src , huge *End_Env ;
  239.    int Done ;
  240.  
  241.    /*
  242.     *  Allocate a chunk of storage to create the Variable name to add
  243.     *  to the Environment table
  244.    */
  245.    Temp_Name = Fmalloc ( 256 ) ;
  246.  
  247.    /*
  248.     *  Extract only the Name portion of the data to add to the Environment
  249.    */
  250.    for ( Src = name , Dest = Temp_Name ;
  251.          *Src && ( *Src != '=' ) ;
  252.         *(Dest++) = *(Src++) ) ;
  253.  
  254.    /*
  255.     *  Ensure that the resulting name is well formed.
  256.    */
  257.    *(Dest++) = '=' ;
  258.    *Dest = 0 ;
  259.  
  260.    /*
  261.     *  Delete this sub string if found in the environment
  262.    */
  263.    Mstr_delenv ( Env , EnvSize , Temp_Name ) ;
  264.  
  265.    /*
  266.     *  Locate the END of the Master table by locating a zero length
  267.     *  String in it
  268.    */
  269.    Sub_Env = Env ;
  270.    for ( ; *Sub_Env ; )
  271.    {
  272.      for ( ; *(Sub_Env++) ; ) ;
  273.    }
  274.  
  275.    /*
  276.     *  Add the new string to the END of the existing environment, with
  277.     *  trincation IF needed
  278.    */
  279.    for ( Dest = (char huge *)(Sub_Env) , Src = name , End_Env = (char huge *) (Env + EnvSize ) ;
  280.          ( Dest < End_Env ) && (*Src) ;
  281.          *(Dest++) = *(Src++) ) ;
  282.  
  283.    Done = -1 ;
  284.    if ( !*Src )
  285.    {
  286.      /*
  287.       *  If the string to add was FULLY added, ensure that the
  288.       *  newly updated environment is properly finished
  289.      */
  290.      Done = 0 ;
  291.      *(Dest++) = 0 ;
  292.      *Dest = 0 ;
  293.    }
  294.  
  295.    /*
  296.     *  As a real safety measure, ensure that the FINAL two bytes of the
  297.     *  Environment are both 0. This will finish the last string AND
  298.     *  ensure that a zero length string is also present
  299.    */
  300.    *(End_Env-1) = 0 ;
  301.   *(End_Env-2) = 0 ;
  302.  
  303.    /*
  304.     *  Free all working storage
  305.    */
  306.    Ffree ( Temp_Name ) ;
  307.  
  308.    return ( Done ) ;
  309. }
  310.  
  311. void main(void)
  312. {
  313.   char far *Env ;
  314.    unsigned EnvSize ;
  315.  
  316.    /*
  317.     *  Locate the Master Table
  318.    */
  319.    Mstr_FindEnvironment ( &Env, &EnvSize ) ;
  320.  
  321.    /*
  322.     *  Describe what we've just found
  323.    */
  324.    printf ( "Env = %Fp Size = %u\n\n" , Env , EnvSize ) ;
  325.  
  326.    /*
  327.     *  Search for, and display LOCATIONS of PATH, FRED and BERT
  328.    */
  329.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  330.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  331.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  332.  
  333.    /*
  334.     *  Add FRED and BERT to the environment
  335.    */
  336.    Mstr_putenv ( Env , EnvSize , "FRED=fred" ) ;
  337.    Mstr_putenv ( Env , EnvSize , "BERT=bert" ) ;
  338.  
  339.    printf ( "\nAdded FRED and BERT to environment\n" ) ;
  340.  
  341.    /*
  342.     *  Search for, and display LOCATIONS of PATH ,FRED and BERT
  343.    */
  344.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  345.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  346.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  347.  
  348.    /*
  349.     *  Delete FRED from the environment
  350.    */
  351.    Mstr_delenv ( Env , EnvSize , "FRED=" ) ;
  352.  
  353.    printf ( "\nDeleted FRED= from the environment\n" ) ;
  354.  
  355.    /*
  356.     *  Search for, and display LOCATIONS of PATH, FRED, and BERT
  357.    */
  358.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  359.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  360.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  361.  
  362.    printf ( "\nIssue the DOS command SET and see that BERT is now set\n" ) ;
  363.  
  364. }
  365.